{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Firmware Build Setup\n",
    "\n",
    "Supported setups:\n",
    "\n",
    "SCOPES:\n",
    "\n",
    "* OPENADC\n",
    "* CWNANO\n",
    "\n",
    "PLATFORMS:\n",
    "\n",
    "* CWLITEARM\n",
    "* CWLITEXMEGA\n",
    "* CWNANO"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This tutorial will introduce you to the software side of ChipWhisperer, including the tutorials themselves. It will also show you how to perform different operations on data based on input from the ChipWhisperer software. This can be used for building your own system which you wish to 'break'. All the `%%bash` blocks can be run either in Jupyter or in your favourite command line environment (note that Jupyter resets your path between blocks).\n",
    "\n",
    "If you haven't run through `!!Introduction_to_Jupyter!!.ipynb` do that now.\n",
    "\n",
    "Assuming you've done that, we can get started on the tutorial."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "SCOPETYPE = 'OPENADC'\n",
    "PLATFORM = 'CWLITEARM'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## What is SimpleSerial"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "SimpleSerial is the communications protocol used for almost all of the ChipWhisperer demo project. It's a very basic serial protocol which can be easily implemented on most systems. This system communicates using a standard asyncronous serial protocol, 38400 baud, 8-N-1.\n",
    "\n",
    "All messages are sent in ASCII-text, and are normally terminated with a line-feed (`'\\n'`). This allows you to interact with the simpleserial system over a standard terminal emulator.\n",
    "\n",
    "`x`\n",
    "\n",
    "> Sending a 'x' resets the buffers. This does not require a line-feed termination. It is suggested to always send a stream of x's to initilize the system in case the device was already in some other mode due to noise/corruption.\n",
    "\n",
    "`k00112233445566778899AABBCCDDEEFF\\n`\n",
    "\n",
    "> Loads the encryption key `00112233445566778899AABBCCDDEEFF` into the system. If not called the system may use some default key.\n",
    "\n",
    "`pAABBCCDDEEFF00112233445566778899\\n`\n",
    "\n",
    "> Encrypts the data `AABBCCDDEEFF00112233445566778899` with the key loaded with the 'k' command. The system will respond with a string starting with r, as shown next.\n",
    "\n",
    "`rCBBD4A2B34F2571758FF6A797E09859D\\n`\n",
    "\n",
    "> This is the response from the system. If data has been encrypted with a 'p' for example, the system will respond with the 'r' sequence automatically. So sending the earlier example means the result of the encryption was `cbbd4a2b34f2571758ff6a797e09859d`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Building the Basic Example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To bulid the basic example, you'll need an appropriate compiler for your target. For the ChipWhisperer Lite/Xmega platform, you'll need `avr-gcc` and `avr-libc`, while if you're using an ARM target (like the ChipWhisperer Lite/STM32 platform), your need the GNU Toolchain for ARM devices. If you're using a target with a different architecture, you'll need to install the relevant compiler. If you're unsure, you can run the block below. If you've got the right stuff installed, you should see some version and copyright info printed for the relevant compiler:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "#check for avr-gcc\n",
    "avr-gcc --version\n",
    "\n",
    "#check for ARM gcc\n",
    "arm-none-eabi-gcc --version"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that you have the relevant toolchain installed, you should be able to build firmware for your desired platform. We'll begin by creating a new project based on simpleserial-base by making a new firmware and copying the files from the project we want to work on:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "cd ../hardware/victims/firmware/\n",
    "mkdir -p simpleserial-base-lab1 && cp -r simpleserial-base/* $_\n",
    "cd simpleserial-base-lab1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we'll build the firmware. You'll need to specify the `PLATFORM` and `CRYPTO_TARGET` for your target. To save you from having to re-enter this info in every make block, you can edit the python below with your platform and crypto_target.\n",
    "\n",
    "Common platforms are CWLITEXMEGA and CWLITEARM. To see a list of platforms leave `PLATFORM` as is.\n",
    "\n",
    "This tutorial doesn't use any crypto, so we can leave `CRYPTO_TARGET` as `NONE`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "CRYPTO_TARGET = \"NONE\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Provided you completed the fields above, you should be able to successfully run the block below."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash -s \"$PLATFORM\" \"$CRYPTO_TARGET\"\n",
    "cd ../hardware/victims/firmware/simpleserial-base-lab1\n",
    "make PLATFORM=$1 CRYPTO_TARGET=$2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Modifying the Basic Example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "At this point we want to modify the system to perform 'something' with the data, such that we can confirm the system is working. To do so, open the file `simpleserial-base.c` in the simpleserial-base-lab1 folder with a code editor such as Programmer's Notepad (which ships with WinAVR).\n",
    "\n",
    "Find the following code block towards the end of the file:\n",
    "\n",
    "```C\n",
    "/**********************************\n",
    " * Start user-specific code here. */\n",
    "trigger_high();\n",
    "\n",
    "//16 hex bytes held in 'pt' were sent\n",
    "//from the computer. Store your response\n",
    "//back into 'pt', which will send 16 bytes\n",
    "//back to computer. Can ignore of course if\n",
    "//not needed\n",
    "\n",
    "trigger_low();\n",
    "/* End user-specific code here. *\n",
    "```\n",
    "\n",
    "Now modify it to increment the value of each data byte:\n",
    "\n",
    "```C\n",
    "/**********************************\n",
    " * Start user-specific code here. */\n",
    "trigger_high();\n",
    "\n",
    "//16 hex bytes held in 'pt' were sent\n",
    "//from the computer. Store your response\n",
    "//back into 'pt', which will send 16 bytes\n",
    "//back to computer. Can ignore of course if\n",
    "//not needed\n",
    "\n",
    "for(int i = 0; i < 16; i++){\n",
    "    pt[i]++;\n",
    "}\n",
    "\n",
    "trigger_low();\n",
    "/* End user-specific code here. *\n",
    " ********************************/\n",
    "```\n",
    "\n",
    "Then rebuild the file with `make`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash -s \"$PLATFORM\" \"$CRYPTO_TARGET\"\n",
    "cd ../hardware/victims/firmware/simpleserial-base-lab1\n",
    "make PLATFORM=$1 CRYPTO_TARGET=$2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Python Script"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll end by uploading the firmware onto the target and communicating with it via a python script. Depending on your target, uploading firmware will be different. For the XMega and STM32 targets, you can use ChipWhisperer's interface. Otherwise, you'll likely need to use and external programmer. If you have a CW1173/Xmega board, you can run the following blocks without modification. After running the final block, you should see two sets of hexadecimal numbers, with the second having values one higher than the first."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll begin by importing the ChipWhisperer module. This will allow us to connect to and communicate with the ChipWhisperer hardware. The ChipWhisperer module also includes analysis software, which we'll be looking at in later tutorials."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import chipwhisperer as cw"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Documentation is available on [ReadtheDocs](https://chipwhisperer.readthedocs.io/en/latest/api.html) or by calling `help()` on the module, submodule, function, etc.:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "help(cw)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we'll need to connect to the scope end of the hardware. Starting with ChipWhisperer 5.1, `cw.scope` will attempt to autodetect which scope type you have (though if you have multiple ChipWhisperers connected, you'll need to specify the serial number). If you'd like, you can still specify the scope type."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scope = cw.scope()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "help(scope)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll also need to setup the interface to the target (typically what we want to attack). Like with scopes, there's a few different interfaces we can use, which are available through `scope.targets.<target_type>`. The default, SimpleSerial, communicates over UART and is almost always the correct choice."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "target = cw.target(scope, cw.targets.SimpleSerial)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we'll do some basic setup. Most of these settings don't matter for now, but take note of the `scope.clock` and `scope.io`, which setup the clock and serial io lines, which needs to be done before programming the target. \n",
    "\n",
    "**Some targets require settings different than what's below. Check the relevant wiki article for your target for more information**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# setup scope parameters\n",
    "if SCOPETYPE == \"OPENADC\":\n",
    "    scope.gain.db = 45\n",
    "    scope.adc.samples = 3000\n",
    "    scope.adc.offset = 1250\n",
    "    scope.adc.basic_mode = \"rising_edge\"\n",
    "    scope.clock.clkgen_freq = 7370000\n",
    "    scope.clock.adc_src = \"clkgen_x4\"\n",
    "    scope.trigger.triggers = \"tio4\"\n",
    "    scope.io.tio1 = \"serial_rx\"\n",
    "    scope.io.tio2 = \"serial_tx\"\n",
    "    scope.io.hs2 = \"clkgen\"\n",
    "elif SCOPETYPE == \"CWNANO\":\n",
    "    scope.io.clkout = 7370000\n",
    "    scope.adc.clk_freq = 7370000\n",
    "    scope.io.tio1 = \"serial_rx\"\n",
    "    scope.io.tio2 = \"serial_tx\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Or, more simply:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scope.default_setup()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that the clock and IO lines are setup, we can program the target. ChipWhisperer includes a generic programming function, `cw.program_target(scope, type, fw_path)`. Here `type` is one of the programmers available in the cw.programmers submodule (`help(cw.programmers)` for more information). `fw_path` is the path to the hex file that you want to flash onto the device.\n",
    "\n",
    "The final part of the binary path should match your platform (`<path>/simpleserial-base-CWLITEARM.hex` for CWLITEARM)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if \"STM\" in PLATFORM or PLATFORM == \"CWLITEARM\" or PLATFORM == \"CWNANO\":\n",
    "    prog = cw.programmers.STM32FProgrammer\n",
    "elif PLATFORM == \"CW303\" or PLATFORM == \"CWLITEXMEGA\":\n",
    "    prog = cw.programmers.XMEGAProgrammer\n",
    "else:\n",
    "    prog = None\n",
    "    \n",
    "fw_path = '../hardware/victims/firmware/simpleserial-base-lab1/simpleserial-base-{}.hex'.format(PLATFORM)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And finally actually programming the device:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cw.program_target(scope, prog, fw_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally, we'll load some text, send it to the target, and read it back. We also capture a trace here, but don't do anything with it yet (that will come in later tutorials). You should see your original text with the received text below it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ktp = cw.ktp.Basic() # object to generate fixed/random key and text (default fixed key, random text)\n",
    "key, text = ktp.next()  # get our fixed key and random text\n",
    "\n",
    "target.simpleserial_write('k', key)\n",
    "target.simpleserial_wait_ack()\n",
    "scope.arm()\n",
    "\n",
    "target.simpleserial_write('p', text)\n",
    "    \n",
    "ret = scope.capture()\n",
    "trace = scope.get_last_trace()\n",
    "output = target.simpleserial_read('r', 16)\n",
    "\n",
    "from binascii import hexlify\n",
    "print(hexlify(output))\n",
    "print(hexlify(text))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also just run:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ret = cw.capture_trace(scope, target, text, key)\n",
    "if ret:\n",
    "    trace = ret\n",
    "    print(hexlify(ret.textout))\n",
    "    print(hexlify(text))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that we're done with this tutorial, we'll need to disconnect from the ChipWhisperer. This will prevent this session from interferening from later ones (most notably with a `USB can't claim interface` error). Don't worry if you forget, unplugging and replugging the ChipWhipserer should fix it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scope.dis()\n",
    "target.dis()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Future Tutorials"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The next tutorials that you run will start using helper scripts to make setup a little faster and more consistent between tutorials. Those scripts run mostly the same setup code that we did here, but if you'd like to see exactly what they're doing, they're all included in the `Helper_Scripts` folder.\n",
    "\n",
    "For example, the scope setup (gain, clock, etc) is taken care of by `Helper Scripts/Setup_Generic.ipynb`."
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
